#include <atomic>
#include <chrono>
#include <cstring>
#include <fstream>
#include <future>
#include <thread>
#include <vector>
#include <filesystem>
#include <memory>
#include "gtest/gtest.h"
#define private public
#include "async_logger.h"
#include "async_fsync.h"
#include "file_output_strategy.h"
#include "console_output_strategy.h"
#undef private

#define UNUSED(x) (void)(x)
namespace Base {
namespace SystemLog {
using namespace std::chrono_literals;

namespace {
constexpr const char* TEST_LOG_DIR = "out/tests/logs";
const char TEST_CHAR = 't';
constexpr int TEST_THREADS = 8;
constexpr int TEST_MESSAGES_COUNT = 1000;
constexpr size_t TEST_MESSAGE_SIZE = 64;
constexpr size_t TEST_MB = 1024 * 1024;
constexpr size_t TEST_BUFFER_SIZE = 1 * TEST_MB;
constexpr uint32_t TEST_FLUSH_INTERVAL_MS = 50;
constexpr size_t TEST_SOFT_FLUSH_THRESHOLD = TEST_BUFFER_SIZE / 4;
constexpr size_t TEST_HARD_FLUSH_THRESHOLD = TEST_BUFFER_SIZE / 2;

class TestOutput {
public:
    ErrCode operator()(const char* data, size_t len) {
        std::lock_guard<std::mutex> lock(mutex_);
        output_.append(data, len);
        totalBytes_ += len;
        return ERR_OK;
    }

    const std::string &GetOutput() {
        std::lock_guard<std::mutex> lock(mutex_);
        return output_;
    }

    size_t GetTotalBytes() {
        std::lock_guard<std::mutex> lock(mutex_);
        return totalBytes_;
    }

    void Clear() {
        std::lock_guard<std::mutex> lock(mutex_);
        output_.clear();
        totalBytes_ = 0;
    }

private:
    std::string output_;
    size_t totalBytes_ = 0;
    std::mutex mutex_;
};

} // namespace

class AsyncFsyncSecurityTest : public testing::Test {
protected:
    static void SetUpTestCase(void);
    static void TearDownTestCase(void);
    void SetUp();
    void TearDown();

    std::unique_ptr<AsyncLogger<TEST_BUFFER_SIZE>> logger_;
    std::shared_ptr<TestOutput> testOutput_;
    std::string testDir_;
};

void AsyncFsyncSecurityTest::SetUpTestCase(void)
{}

void AsyncFsyncSecurityTest::TearDownTestCase(void)
{}

void AsyncFsyncSecurityTest::SetUp()
{
    // 创建测试目录
    testDir_ = std::string(TEST_LOG_DIR) + "/test_async_fsync_security_logs";
    std::filesystem::create_directories(testDir_);

    // 创建日志器和测试输出
    logger_ = std::make_unique<AsyncLogger<TEST_BUFFER_SIZE>>();
    testOutput_ = std::make_shared<TestOutput>();
    
    // 创建一个自定义输出策略来替代SetOutputFunction
    class TestOutputStrategy : public IOutputStrategy {
        std::shared_ptr<TestOutput> testOutput_;
    public:
        TestOutputStrategy(std::shared_ptr<TestOutput> output) : testOutput_(std::move(output)) {}
        ErrCode Write(const char* data, size_t len) override {
            return (*testOutput_)(data, len);
        }
        ErrCode Flush() override { return ERR_OK; }
        ErrCode Close() override { return ERR_OK; }
        std::string GetName() const override { return "TestOutputStrategy"; }
    };
    
    logger_->AddOutputStrategy(std::make_unique<TestOutputStrategy>(testOutput_));
    logger_->SetFlushThreshold(TEST_SOFT_FLUSH_THRESHOLD, TEST_HARD_FLUSH_THRESHOLD);
    logger_->SetFlushInterval(TEST_FLUSH_INTERVAL_MS);
}

void AsyncFsyncSecurityTest::TearDown()
{
    if (logger_) {
        logger_->Stop();
        logger_.reset();
    }
    
    // 清理测试目录
    try {
        if (std::filesystem::exists(testDir_)) {
            std::filesystem::remove_all(TEST_LOG_DIR);
        }
    } catch (const std::filesystem::filesystem_error &ex) {
        GTEST_LOG_(ERROR) << "Failed to remove test directory: " << ex.what() << std::endl;
    }
}

/**
 * @tc.name: AsyncFsyncSecurityTest_001
 * @tc.desc: memory leak detection with AsyncFsync
 * @tc.type: SECURITY
 */
TEST_F(AsyncFsyncSecurityTest, AsyncFsyncSecurityTest_001)
{
    {
        auto& logger = AsyncLogger<>::GetInstance();

        FileOutputOptions options;
        options.filePathPattern = testDir_ + "/memory_test.log";
        options.useAsyncFsync = true;
        options.asyncFsyncIntervalMs = 100;

        auto fileStrategy = std::make_unique<FileOutputStrategy>(options);
        logger.AddOutputStrategy(std::move(fileStrategy));
        logger.Start();

        const std::string msg(TEST_MESSAGE_SIZE, TEST_CHAR);
        for (int i = 0; i < TEST_MESSAGES_COUNT; ++i) {
            logger.Append(msg.c_str(), msg.size());
        }

        logger.ForceSync();
        logger.Stop();
    }

    // 给一些时间让异步操作完成
    std::this_thread::sleep_for(std::chrono::milliseconds(100));

    // 重启AsyncFsync以清理任何遗留状态
    auto& asyncFsync = AsyncFsync::GetInstance();
    asyncFsync.Restart();

    // 检查AsyncFsync状态
    EXPECT_EQ(asyncFsync.GetFileCount(), static_cast<size_t>(0)); // 没有遗留的文件描述符
}

/**
 * @tc.name: AsyncFsyncSecurityTest_002
 * @tc.desc: resource cleanup on abnormal shutdown
 * @tc.type: SECURITY
 */
TEST_F(AsyncFsyncSecurityTest, AsyncFsyncSecurityTest_002)
{
    auto& asyncFsync = AsyncFsync::GetInstance();
    
    // 模拟添加多个文件描述符
    for (int i = 0; i < 5; ++i) {
        std::string filename = testDir_ + "/test_" + std::to_string(i) + ".log";
        std::ofstream file(filename);
        file.close();
        
        int fd = open(filename.c_str(), O_WRONLY | O_APPEND);
        if (fd != -1) {
            asyncFsync.AddFile(fd);
        }
    }
    
    size_t initialCount = asyncFsync.GetFileCount();
    EXPECT_GT(initialCount, static_cast<size_t>(0));
    
    // 强制重启（模拟异常关闭）
    asyncFsync.Restart();
    
    // 验证所有资源都被清理
    EXPECT_EQ(asyncFsync.GetFileCount(), static_cast<size_t>(0));
}

/**
 * @tc.name: AsyncFsyncSecurityTest_003
 * @tc.desc: thread safety under high contention
 * @tc.type: SECURITY
 */
TEST_F(AsyncFsyncSecurityTest, AsyncFsyncSecurityTest_003)
{
    auto& asyncFsync = AsyncFsync::GetInstance();
    std::atomic<bool> start{false};
    std::atomic<int> successCount{0};
    std::atomic<int> failCount{0};
    
    // 创建多个线程同时操作AsyncFsync
    std::vector<std::thread> threads;
    for (int i = 0; i < TEST_THREADS; ++i) {
        threads.emplace_back([&, i]() {
            while (!start) {
                std::this_thread::yield();
            }
            
            for (int j = 0; j < 100; ++j) {
                std::string filename = testDir_ + "/thread_" + std::to_string(i) + "_" + std::to_string(j) + ".log";
                std::ofstream file(filename);
                file.write("test data", 9);
                file.close();
                
                int fd = open(filename.c_str(), O_WRONLY | O_APPEND);
                if (fd != -1) {
                    asyncFsync.AddFile(fd);
                    successCount.fetch_add(1);
                } else {
                    failCount.fetch_add(1);
                }
            }
        });
    }
    
    start = true;
    for (auto& t : threads) {
        t.join();
    }
    
    // 验证没有出现竞态条件导致的崩溃
    EXPECT_GT(successCount.load(), 0);
    GTEST_LOG_(INFO) << "Success operations: " << successCount.load() 
                     << ", Failed operations: " << failCount.load();
    
    // 清理
    asyncFsync.Restart();
}

} // namespace SystemLog
} // namespace Base
